/*
 *  Controller.m: Controller Object of Gomoku.app
 *
 *  Copyright (c) 2000 Nicola Pero <n.pero@mi.flashnet.it> (parts marked (NP))
 *  Copyright (c) 2004 Adam Nohejl <adam.nohejl@kppm.cz> (parts marked (Loki))
 *  
 *  Author: Nicola Pero (parts marked (NP))
 *  Date: April, September 2000
 *
 *  Author: Adam Nohejl (parts marked (Loki))
 *  Date: 2004-02-21 - 2004-04-08
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */



#include "Controller.h"
#include "Board.h"

/* (Loki){ */

#import "Prefs.h"

#define extSavedGame	".gomokuSave"

@interface NSWindow (NSWindowGomokuAdditions)
- (NSPoint)frameTopLeftPoint;
@end

@implementation NSWindow (NSWindowGomokuAdditions)
- (NSPoint)frameTopLeftPoint{
	NSRect frame = [self frame];
	frame.origin.y+=frame.size.height;
	return frame.origin;
}
@end

/* }(Loki) */

@implementation Controller

/* formerly: - init: (int) cnt;*/
- (void)setUpWindow{
	NSMatrix*		matrix			= nil;
	NSImageCell*	cell			= nil;
	NSImage*		image			= nil;
	NSRect			winFrame;
	int				newBoardSize;
	/* Li Wei Nan */
	gameType = [prefs gameType];
	gameTile = [prefs firstTurn];
	isUserFirstMove = YES;
	/* (Loki){ */
	newBoardSize	= [prefs boardSize];
	
	if(boardSize!=newBoardSize){
		[board release];
		board = nil;
	}
	boardSize = newBoardSize;
	/* } */
	
	/* (NP, modified a lot by Loki){*/
	if(!board){
		/* CELL PROTOTYPE */
		cell = [[NSCell alloc] init];
		AUTORELEASE (cell);
		[cell setBordered: NO];
		[cell setBezeled: NO];
		[cell setEditable: NO];
		[cell setSelectable: NO];
		/* (Loki){ */
		image = [NSImage imageNamed: @"Empty"];
		[image setScalesWhenResized:YES];
		[image setSize:NSMakeSize([prefs boardZoom],[prefs boardZoom])];
		/* }(Loki) */
		[cell setImage: image];
		
		/* MATRIX(CELL PROTO.) */
		matrix = [[NSMatrix alloc] initWithFrame: NSZeroRect
											mode: NSTrackModeMatrix 
									   prototype: cell
									numberOfRows: newBoardSize 
								 numberOfColumns: newBoardSize];
		AUTORELEASE (matrix);
		[matrix setIntercellSpacing: NSMakeSize (0, 0)];
		[matrix setAutoresizingMask: NSViewNotSizable];
		[matrix sizeToFit];
		[matrix setTarget: self];
		[matrix setAction: @selector (userMove:)];
		
		/* MAINBOARD(MATRIX) */
		board = [[MainBoard alloc] initWithMatrix: matrix];
	}
	
	/* get up-to-date = zoomed size of the content view */
	
	if(!boardWin){
		/* WINDOW */
		winFrame.size = [matrix frame].size;
		winFrame.origin = NSMakePoint(100,100);
		boardWin = [[NSWindow alloc]
					initWithContentRect: winFrame
					styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)
					backing: NSBackingStoreBuffered
					defer: YES];
		[boardWin setTitle: _(@"Gomoku")];
		[boardWin setReleasedWhenClosed: NO];
		
		contentSize = [matrix frame].size;
	}
	
	/* new matrix generated == change of size: */
	if(matrix)
		[boardWin setContentView: matrix];
}

- (void) dealloc{
	RELEASE (board);
	[boardWin release]; /* (Loki) */
	[super dealloc];
}

- (void) applicationDidFinishLaunching: (NSNotification *)aNotification{
	[self newGame:self];
}

/* }(NP, modified a lot by Loki) */

/* (NP){ */
- (void) userMove: (id) sender
{	
	if(isUserFirstMove==YES && [prefs gameType]==h2c && [prefs firstTurn]==computer) {
		gameTile=human;
		isUserFirstMove=NO;
	}
	
	// user has a move
	if ([sender isKindOfClass: [NSMatrix class]]) {		
		
		/* avoid squares already occupied */
		if (![board isFreeRow:[(NSMatrix *)sender selectedRow] column:[(NSMatrix *)sender selectedColumn]]) {
			return;
		}		
		
		NSUndoManager *undoMgr = [boardWin undoManager];			
		
		[[undoMgr prepareWithInvocationTarget:self] undoMoveInRow:[(NSMatrix *)sender selectedRow] 
														   column:[(NSMatrix *)sender selectedColumn]
														 currTile:gameTile];
		
		[board userMoveInRow: [(NSMatrix *)sender selectedRow]
					  column: [(NSMatrix *)sender selectedColumn]
					 setTile: gameTile];				
    }
	// after user moves, computer should move if the mode is human vs. computer
	if([prefs gameType] == h2c) {
		[board performComputerMove];
		
		NSUndoManager *undoMgr = [boardWin undoManager];
		[[undoMgr prepareWithInvocationTarget:self] undoMoveInRow:[[board board] lastRow]
														   column:[[board board] lastColumn]
														 currTile:computer];
	} else {
		gameTile = (gameTile == human)? computer : human;
	}
}

- (void) undoMoveInRow:(int)i column:(int)j currTile:(tile)currTile{
	//NSLog(@"i: %d, j: %d", i, j);
	
	NSUndoManager *undoMgr = [boardWin undoManager];			
	[[undoMgr prepareWithInvocationTarget:self] redoMoveInRow:i
													   column:j
													 currTile:currTile];	
	
	
	[board setTile:(tile)nothing inRow:i column:j];	
	[[board board] setTile:(tile)nothing inRow:i column:j];
	
	gameTile = (gameTile == human)? computer : human;
}

- (void) redoMoveInRow:(int)i column:(int)j currTile:(tile)currTile {
	//NSLog(@"redo: %d", currTile);
	
	NSUndoManager *undoMgr = [boardWin undoManager];			
	
	[[undoMgr prepareWithInvocationTarget:self] undoMoveInRow:i
													   column:j
													 currTile:currTile];	
		
	[board setTile:(tile)currTile inRow:i column:j];	
	[[board board] setTile:(tile)currTile inRow:i column:j];
	
	gameTile = (gameTile == human)? computer : human;
}

/* (Loki){ */
- (IBAction) newGame:(id)sender{
	//NSLog(@"[controller newGame]");
	[self		setUpWindow];					/* update the window / board if needed */
	[prefs		setUp];
	[board		newGame];						/* clear the board if necessary */
	isUserFirstMove = YES;
	if(sender)
		[boardWin	makeKeyAndOrderFront: self];
	/* else auto by prefs, don't order front */
	if([prefs firstTurn]==computer && [prefs gameType]==h2c)
		[board performComputerMove];
}

- (IBAction) open:(id)sender{
	/*	NSOpenPanel *panel = [NSOpenPanel openPanel];
	 [panel setAllowsMultipleSelection:NO];
	 if ([panel runModalForTypes:[NSArray arrayWithObject:extSavedGame]])
	 [self application:nil openFile:[panel filename]];
	 
	 */
}

- (IBAction) save:(id)sender{
	/*	NSSavePanel *panel = [NSSavePanel savePanel];
	 [panel setExtensionHidden:YES];
	 [panel setCanSelectHiddenExtension:NO];
	 if([panel runModalForDirectory:nil file: [NSLocalizedString(@"untitled",@"Default name for saved game") stringByAppendingString:extSavedGame]] != NSFileHandlingPanelOKButton)
	 return;
	 if(![NSKeyedArchiver archiveRootObject:.... toFile:[panel filename]])
	 NSBeep();*/
	/*TODO handle err */
	
}

- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename{
	/*	PasteboardBuffer*	newPboard;
	 
	 if(!(..... = [NSKeyedUnarchiver unarchiveObjectWithFile:filename])){
	 NSBeep(); -* TODO err hdling *-
	 return NO;
	 }
	 .....*/
	return YES;
}


- (void)	setDifficultyLevel:(int)level{
	[board setDifficultyLevel:level];
}
- (void)	setSounds:(BOOL)s theme:(int)t zoom:(int)z{
	NSSize newContentSize;
	
	//NSLog(@"c-setSounds:...zoom:%i",z);
	
	[board setSounds:s theme:t zoom:z];
	
	newContentSize = [[board refreshMatrix] frame].size;
	if(newContentSize.width != contentSize.width){
		//NSLog(@" newContentSize.width != contentSize.width");
		contentSize = newContentSize;
		[boardWin setContentSize:   contentSize];
		
		NSRect		winFrame	= [boardWin frame];
		NSRect		scrVFrame	= [[boardWin screen] visibleFrame];
		NSPoint		topLeft 	= [boardWin frameTopLeftPoint];
		
		if(
		   winFrame.origin.y		< 0 &&
		   topLeft.y				< (scrVFrame.origin.y + scrVFrame.size.height - 20)
		   ){
			//NSLog(@" ->move win");
			winFrame.origin.y= scrVFrame.origin.y + 20;
		}
		[boardWin setFrame:winFrame display:YES];
	}
	
}

- (BOOL)	newGameIfUserHadNotPlayed{
	if(![board humanTurnsPlayed]){
		[self newGame:nil];
		return YES;
	}
	return NO;
}

/* }(Loki) */

@end

